#pragma one

#include <unordered_map>
#include "Connection.hpp"
#include "Epoller.hpp"
#include <sys/epoll.h>

class Reactor
{
    const static int gnum = 64;
    
    public:
    Reactor()
    :_isrunning(false)
    {}

    void AddConnection(int fd,uint32_t events,func_t recver,func_t sender,func_t excepter)
    {
        //1.创建connection
        Connection* conn = new Connection(fd);
        conn->Register(recver,sender,excepter);
        conn->SetEvents(events);
        conn->SetSelf(this);//指向这个反应堆

        //2.设定反应堆对conn的关心
        _epoller.AddEvent(fd,events);//在构造函数中会自动调用对于epoller的默认构造

        //3.添加到映射中
        _connections.insert(std::make_pair(fd,conn));


    }

    bool ConnectionIsExists(int sockfd)
    {
        auto it = _connections.find(sockfd);//如果迭代器为end()说明是空
        return it!=_connections.end();
    }

    void RemoveConnection(int sockfd)//删除connection
    {
        if(!ConnectionIsExists(sockfd)) return;
        // 1. 去掉epoll对该文件fd的关心
        _epoller.DelEvent(sockfd);
        // 2. 服务器端也要关闭sockfd
        _connections[sockfd]->Close();
        // 3. 释放connection
        delete _connections[sockfd];
        _connections.erase(sockfd);
    }

    void LoopOnce(int timeout)
    {
        int n = _epoller.Wait(_revs,gnum,timeout);
        for(int i=0;i<n;i++)//表示有n个事件需要处理
        {
            //找出对应事件就绪的fd
            int sockfd = _revs[i].data.fd;
            //找出就绪的事件是什么
            uint32_t revents = _revs[i].events;

            if(!ConnectionIsExists(sockfd))
                _connections.erase(sockfd);

            //如果事件异常，让他处于读和写事件，在读写事件中触发异常函数退出
            if(revents&EPOLLHUP)
                _connections[sockfd]->SetEvents(EPOLLIN | EPOLLOUT);
            else if(revents&EPOLLERR)
                _connections[sockfd]->SetEvents(EPOLLIN | EPOLLOUT);
            else if(revents&EPOLLIN)
            {
                if(_connections[sockfd]->_recver!=nullptr)
                    _connections[sockfd]->_recver(_connections[sockfd]);
            }
            else if(revents&EPOLLOUT)
            {
                if(_connections[sockfd]->_sender!=nullptr)
                    _connections[sockfd]->_sender(_connections[sockfd]);
            }
        }

    }


    //事件派发函数
    void Dispatcher()
    {
        int timeout = -1;//代表会一直等着，直到事件发生
        _isrunning = true;
        while(1)
        {
            LoopOnce(timeout);//循环函数 
            Debug();   
        }
        _isrunning = false;

    }
    void EnableReadWrite(int sockfd, bool readable, bool writeable)
    {
        uint32_t events = (readable?EPOLLIN:0) | (writeable ? EPOLLOUT : 0) | EPOLLET;
        if(ConnectionIsExists(sockfd))
        {
            // 1. 修改我们写的connection关心的事件
            _connections[sockfd]->SetEvents(events);

            // 2. 写透到内核中
            _epoller.ModEvent(sockfd, events);
        }
    }

    void Debug()
    {
        std::cout << "------------------------------------" << std::endl;
        for(auto &connection : _connections)
        {
            std::cout << "fd : " << connection.second->Sockfd() << ", ";
            uint32_t events = connection.second->Events();
            if((events & EPOLLIN) && (events & EPOLLET))
                std::cout << "EPOLLIN | EPOLLET, ";
            if((events & EPOLLOUT) && (events & EPOLLET))
                std::cout << "EPOLLOUT | EPOLLET";
            std::cout << std::endl;
        }
        std::cout << "------------------------------------" << std::endl;
    }

    ~Reactor()
    {}

    private:
    std::unordered_map<int,Connection*> _connections;//管理fd对于的connection对象
    struct epoll_event _revs[gnum];//就绪队列
    Epoller _epoller;
    bool _isrunning;

};